/*
 * Author: Nathan Judkins
 * Date: November 7th, 2012
 * 
 * This class contains the paper which an author has submitted, along with
 * the reviewers assigned to this paper and their reviews and whether or not
 * it has been accepted.
 */

package Model;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class Paper
{
  /**
   * Contains the author's name
   */
  private final User my_author;

  /**
   * File object that holds the author's paper
   */
  private File my_manuscript;

  /**
   * File object that holds whether or not the author is recommended
   */
  private File my_recommendation;

  /**
   * A map that directly connects the author's reviewers to their reviews
   */
  private Map<User, File> my_reviewers_to_reviews;

  /**
   * Contains the user who is subprogram chair for this paper
   */
  private User my_subprogram_chair;

  /**
   * The title for this paper in String.
   * */
  private String my_title;

  /**
   * Integer value that says whether or not the paper has been accepted
   * 
   * 0 for no decision has been made 1 for yes -1 for no
   */
  private int my_decision;
  
  private boolean my_assigned;
  
  /**
   * Paper object that has no assigned reviewers or 
   * Subprogram chairs. Just the basic info.
   * 
   * @param the_title Title of manuscript
   * @param the_author the User who submitted this manuscript
   * @param the_manuscript the author's paper.
   */
  public Paper(final String the_title, final User the_author,
      final File the_manuscript_file)
  {
    my_title = the_title;
    my_author = the_author;
    my_manuscript = the_manuscript_file;
    my_reviewers_to_reviews = new HashMap<User, File>();
    my_subprogram_chair = null; //TODO this may need to be changed
    my_decision = 0;
    my_assigned = false;
  }
  
  /**
   * A paper has a title, author, its associated sub-program chair, and its
   * manuscript file. In construction, manuscript file is non null.
   * 
   * 
   * @author Nathan Judkins
   * @param the_title
   *          The title of this conference paper
   * @param the_author
   *          The author of this conference paper
   * @param the_sub_chair
   *          The subprogram chair associated to this paper
   * @param the_manuscript_file
   *          The file for this conference paper
   * */
  public Paper(final String the_title, final User the_author,
      final User the_sub_chair, final File the_manuscript_file)
  {
    my_title = the_title;
    my_author = the_author; //assert that the_author != the_sub_chair
    
    if (the_author.equals(the_sub_chair)) {
      throw new IllegalArgumentException("Cannot assign the paper " + the_title
          + " because " + the_sub_chair + " is the author of this paper");
    }
    my_subprogram_chair = the_sub_chair;
    my_manuscript = the_manuscript_file.getAbsoluteFile();
    my_reviewers_to_reviews = new HashMap<User, File>(); 
    my_decision = 0;
    my_assigned = true;
  }

/**
 * @return Just returns the Reviewers to their reviews.
 */
  public Map<User, File> getMyReviewAssociation()
  {
    return my_reviewers_to_reviews;
  }
  
  /**
   * Should modify the Reviewer's File object or can
   * be used to add a User so that they become a reviewer
   * 
   * @param the_user the Reviewer associated with this Paper
   * @param the_review the actual review 
   */
  public void editReview(User the_user, File the_review)
  {
    my_reviewers_to_reviews.put(the_user, the_review);
  }
  
  
  
  /*
   * Everything below this should be getters and setters and
   * the equals method
   */
  
  /**
   * Returns the Subprogram Chair's
   * recommendation
   * 
   * @return File that is SPC recommendation
   */
  public File getRecommendation()
  {
    return my_recommendation;
  }

/**
 * 0 for no decision has been made 
 * 1 for yes 
 * -1 for no
 * 
 * @return Returns the Program Chair's decision
 */
  public int getDecision()
  {
    return my_decision;
  }

  /**
   * Returns the User that is
   * Subprogram chair associated 
   * with this manuscript.
   * 
   * @return The Subprogram chair for this Paper
   */
  public User getSubprogramChair()
  {
    return my_subprogram_chair;
  }

  /**
   * File object that contains 
   * the author's manuscript
   * 
   * @return The author's Paper
   */
  public File getManuscript()
  {
    return my_manuscript;
  }

  /**
   * Returns the User/author that submitted
   * this manuscript 
   * 
   * @return The author of this paper
   */
  public User getAuthor()
  {
    return my_author;
  }

  /**
   * Returns the title of this paper
   * (should only be used for display purposes).\
   * 
   * @return the title of the manuscript
   */
  public String getTitle()
  {
    return my_title;
  }
  
  public boolean isAssigned() {
  	return my_assigned;
  }
  
  //TODO May need to be changed in the future... the field's value is public
  public void setSubprogramChair(final User the_subprogram)
  {
    my_subprogram_chair = the_subprogram;
    my_assigned = true;
  }
  
  /*TODO Need to have the ability to change aspects of the manuscript... 
   * is it enforced in Paper (aka only the author can access changing the 
   * manuscript... only the SPC can edit recommendations... etc)
  */
  public void editManuscript(final File the_manuscript)
  {
    my_manuscript = the_manuscript;
  }
  
  /**
   * Changes this Paper's title to the new title.
   * 
   * @author Paul Schultz (ps87@uw.edu)
   * @param the_title
   */
  // needed method for editing paper through GUI.
  public void editTitle(final String the_title)
  {
    my_title = the_title;
  }
  
/*  public void editTitle(final String the_title)
  {
    my_title = the_title;
  }*/
  
  public void editRecommendation(final File the_recommendation)
  {
    my_recommendation = the_recommendation;
  }
  
  public void editDecision(final int the_decision)
  {
    my_decision = the_decision;
  }

  @Override
  public int hashCode()
  {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((my_author == null) ? 0 : my_author.userName().hashCode());
    result = prime * result + ((my_title == null) ? 0 : my_title.hashCode());
    return result;
  }

  
  /**
   * Tests equality of different papers based on title, authors, sub-program chairs,
   * manuscripts and decision. Method could fail if manuscript is NULL. Creation
   * of papers should assert that manuscripts are NON-NULL. Otherwise,this
   * method returns true if both objects/papers are equal.
   * 
   * @author InnoIrving Estrera
   * @param the_other
   *          The other object/paper to be compared
   * @return Returns true if both objects/papers are equal.
   * */
  public boolean equals(final Object the_other)
  {
    if (this == the_other)
    {
      return true;
    } else if ((the_other != null) && (the_other.getClass() == getClass()))
    {
      final Paper the_other_paper = (Paper) the_other;
      final boolean same_title = my_title.equals(the_other_paper.getTitle());
      final boolean same_authors = my_author
          .equals(the_other_paper.getAuthor());
      boolean same_manuscripts = false;
      if (my_manuscript != null)
      { // if this paper has a manuscript
      
        same_manuscripts = my_manuscript.getName().equals(the_other_paper.getManuscript().getName());
       
      }
//      final boolean same_decision = (my_decision == the_other_paper.getDecision());
      return (same_title && same_authors && same_manuscripts);
    } else
    {
      return false;
    }
  }
 
  
}
